//Documentation complete
/**
 * @author Kazu
 * @version 2009AP06
 */

package control;

import static problemDomain.ErrorBean.*;
import static problemDomain.ErrorBean.ErrorCode.*;
import problemDomain.*;
import broker.*;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
 * Control object for reservation object operations.
 */
public class ReservationControl extends Control {
	
	/* Attributes */
	
	private static DateFormat DATE_FORMAT = new SimpleDateFormat("dd-MMM-yyyy");
	
	private ReservationBroker rb;
	private ConfigFileBroker cfb;
	
	/* END Attributes */
	
	
	/* Constructors */
	
	/**
	 * Constructs a <code>ReservationControl</code>.
	 * @throws ErrorBean if the database is not available
	 */
	public ReservationControl () throws ErrorBean {
		this.rb = ReservationBroker.getBroker();
		this.cfb = ConfigFileBroker.getBroker();
	}
	
	/* END Constructors */
	
	
	/* Methods */
	
	/**
	 * Creates a new reservation which is created by an employee.
	 * @param firstname the first name of the person making the reservation
	 * @param lastname the last name of the person making the reservation
	 * @param phone the phone number of the person making the reservation
	 * @param numPeople the number of people attending on the reservation date
	 * @param day the day of the reservation
	 * @param month the month of the reservation
	 * @param year the year of the reservation
	 * @param hour the hour of the reservation
	 * @param minute the minute of the reservation
	 * @param description the description for the reservation
	 * @param employee the employee that created the reservation
	 * @throws ErrorBean if the input data are not correct
	 */
	public void create (String firstname, String lastname, String phone,
			String numPeople, String day, String month, String year, String hour, String minute,
			String description, EmployeeAccountBean employee) throws ErrorBean {
		Calendar resDate = checkDate(year, month, day, hour, minute);
		ReservationBean res;
		res = new ReservationBean(0, firstname, lastname, phone, checkNumberOfPeople(numPeople), Calendar.getInstance(), resDate, description, employee, null);
		
		rb.persist(res);
	}
	
	/**
	 * Create a new reservation which is created by a patron.
	 * @param firstname the first name of the person making the reservation
	 * @param lastname the last name of the person making the reservation
	 * @param phone the phone number of the person making the reservation
	 * @param numPeople the number of people attending on the reservation date
	 * @param day the day of the reservation
	 * @param month the month of the reservation
	 * @param year the year of the reservation
	 * @param hour the hour of the reservation
	 * @param minute the minute of the reservation
	 * @param description the description of the reservation
	 * @param patron the registered patron that placed the reservation
	 * @throws ErrorBean if the input data are not correct
	 */
	public void create (String firstname, String lastname, String phone,
			String numPeople, String day, String month, String year, String hour, String minute,
			String description, RegisteredPatronAccountBean patron) throws ErrorBean {
		ReservationBean res =
			new ReservationBean(
				0,
				firstname,
				lastname,
				phone,
				checkNumberOfPeople(numPeople),
				Calendar.getInstance(),
				checkDate(year, month, day, hour, minute),
				description,
				null,
				patron);
		rb.persist(res);
	}
	
	/**
	 * Create a new reservation which is created by a patron.
	 * @param firstname the first name of the person making the reservation
	 * @param lastname the last name of the person making the reservation
	 * @param phone the phone number of the person making the reservation
	 * @param numPeople the number of people attending on the reservation date
	 * @param date the date of the reservation
	 * @param hour the hour of the reservation
	 * @param minute the minute of the reservation
	 * @param description the description of the reservation
	 * @param patron the registered patron that placed the reservation
	 * @throws ErrorBean if the input data are not correct
	 */
	public void create (String firstname, String lastname, String phone,
			String numPeople, String date, String hour, String minute,
			String description, RegisteredPatronAccountBean patron) throws ErrorBean {
		
		try {
			ReservationBean res =
				new ReservationBean(
					0,
					firstname,
					lastname,
					phone,
					checkNumberOfPeople(numPeople),
					Calendar.getInstance(),
					convertDateToCalendar(DATE_FORMAT.parse(date), hour+":"+minute),
					description,
					null,
					patron);
			rb.persist(res);
		} catch (ParseException e) {
			throwError(
				RESERVATION_DATERESERVED_INVALID,
				date,
				this);
		}
	}
	
	/**
	 * Searches for reservations which match the search criteria.
	 * @param firstname the first name to search for (<code>""</code> excludes this field when searching)
	 * @param lastname the last name to search for (<code>""</code> excludes this field when searching)
	 * @param phone the phone number to search for (<code>""</code> excludes this field when searching)
	 * @param day the day to search for (<code>""</code> excludes this field when searching)
	 * @param month the month to search for (<code>""</code> excludes this field when searching)
	 * @param year the year to search for (<code>""</code> excludes this field when searching)
	 * @return a <code>List</code> of results
	 * @throws ErrorBean if the input data are not correct
	 */
	public List<ReservationBean> search(String firstname, String lastname, String phone,
						String day, String month, String year) throws ErrorBean {
		ReservationBean searchBean = new ReservationBean();
		searchBean.setFirstname(firstname);
		searchBean.setLastname(lastname);
		searchBean.setPhone(phone);	
		if (!day.equals("") && !month.equals("") && !year.equals(""))
			searchBean.setReservationDate(checkDate(year, month, day));
		return rb.search(searchBean);
	}
	
	/**
	 * Searches for reservations which match the search criteria.
	 * @param patron the patron to search for
	 * @return a <code>List</code> of results
	 * @throws ErrorBean if the input data are not correct
	 */
	public List<ReservationBean> search (RegisteredPatronAccountBean patron) throws ErrorBean {
		ReservationBean searchBean = new ReservationBean();
		searchBean.setPatron(patron);
		return rb.search(searchBean);
	}
	
	/**
	 * Searches for reservations by date.
	 * @param day the day to search for
	 * @param month the month to search for
	 * @param year the year to search for
	 * @param type the type of search to perform
	 * @return a <code>List</code> of results
	 * @throws ErrorBean if the input data are not correct
	 */
	public List<ReservationBean> searchByDate (String day, String month, 
			String year, String type) throws ErrorBean {
		ReservationBean searchBean = new ReservationBean();
		searchBean.setReservationDate(checkDate(year, month, day));
		return rb.search(searchBean, type);
	}
	
	/**
	 * Updates a reservation.
	 * @param id the ID of the reservation
	 * @param firstname the first name of the person making the reservation
	 * @param lastname the last name of the person making the reservation
	 * @param phone the phone number of the person making the reservation
	 * @param numPeople the number of people attending on the reservation date
	 * @param day the day of the reservation
	 * @param month the month of the reservation
	 * @param year the year of the reservation
	 * @param hour the hour of the reservation
	 * @param minute the minute of the reservation
	 * @param description the description of the reservation
	 * @throws ErrorBean if the input data are not correct
	 */
	public void update (String id, String firstname, String lastname, String phone, 
			String numPeople, String day, String month, String year, String hour, String minute,
			String description) throws ErrorBean {
		ReservationBean res =
			new ReservationBean(
				checkId(id),
				firstname,
				lastname,
				phone,
				checkNumberOfPeople(numPeople),
				Calendar.getInstance(),
				checkDate(year, month, day, hour, minute),
				description, null, null);
		
		rb.persist(res);
	}
	
	/**
	 * Deletes a reservation.
	 * @param id the ID of the reservation
	 * @throws ErrorBean if the input data are not correct
	 */
	public void delete (String id) throws ErrorBean {
		ReservationBean res =
			new ReservationBean(
				checkId(id));
		rb.remove(res);
	}
	
	/**
	 * Lists all reservations.
	 * @return a <code>List</code> of results
	 * @throws ErrorBean if there is an error retrieving the data
	 */
	public List<ReservationBean> listAll () throws ErrorBean {
		return rb.listAll();
	}
	
	/**
	 * Lists all operational hours.
	 * @return a <code>List</code> of results
	 * @throws ErrorBean if there is an error retrieving the data
	 */
	public List<String> listOperationHour() throws ErrorBean {
		return cfb.listAll("operationHour");
	}
	
	/* END Methods */
	
	
	/* Local Methods */
	
	/**
	 * Convert a Date object to a Calendar object.
	 * @param date The Date to convert
	 * @return c the converted Calendar
	 */
	private Calendar convertDateToCalendar(Date date, String time) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		String [] fields = time.split(":");
		c.set(Calendar.HOUR, Integer.parseInt(fields[0]));
		c.set(Calendar.MINUTE, Integer.parseInt(fields[1]));
		return c;
	}
	
	/* END Local Methods */
	
	
	/* Data Checks */
	
	private Calendar checkDate (String year, String month, String day) throws ErrorBean {
		Calendar date = Calendar.getInstance();
		try {
			date.set(Integer.parseInt(year), Integer.parseInt(month), Integer.parseInt(day));
		} catch (NumberFormatException e) {
			throwError(
				RESERVATION_DATERESERVED_INVALID,
				day + " " + month + " " + year,
				this);
		}
		return date;
	}
	
	private Calendar checkDate (String year, String month, String day, String hour, String minute) throws ErrorBean {
		Calendar date = Calendar.getInstance();
		try {
			int monthInt = Integer.parseInt(month);
			date.set(Integer.parseInt(year), Integer.parseInt(month), Integer.parseInt(day),
				Integer.parseInt(hour), Integer.parseInt(minute));
			if (monthInt != date.get(Calendar.MONTH)) {
				throw new NumberFormatException();
			}
		} catch (NumberFormatException e) {
			throwError(
				RESERVATION_DATERESERVED_INVALID,
				day + " " + month + " " + year + " " + hour + " " + minute,
				this);
		}
		return date;
	}
	
	private int checkId (String id) throws ErrorBean {
		return checkInt(id, RESERVATION_ID_INVALID, this);}
	
	private int checkNumberOfPeople (String number) throws ErrorBean {
		return checkInt(number, RESERVATION_NUMBEROFPEOPLE_INVALID, this);}
	
}
